home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / xgakit.exe / XGAKIT.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-05-06  |  33.4 KB  |  1,191 lines

  1. ;
  2. ;    XGA Adapter Programmer's Toolkit, version 1.1
  3. ;        by Bert Tyler of Tyler Software
  4. ;        CIS ID:  73477,433
  5. ;        (From Internet/BITNET: 73477.433@compuserve.com)
  6. ;    Copyright 1990, 1991 Tyler Software
  7. ;    (except, of course, for those parts copied right out of IBM's
  8. ;    "Preliminary XGA Video Subsystem Hardware Users Guide")
  9. ;        ((which is most of the code, really...))
  10. ;
  11. ;    Free for use in commercial, shareware or freeware applications
  12. ;
  13. ;    Routines in this module:
  14. ;
  15. ;    int xga_detect()
  16. ;        returns    0 if no XGA adapter found
  17. ;            non-zero if XGA adapter found
  18. ;        bits:    0 - XGA adapter found
  19. ;            1 - XGA monitor is color, not mono
  20. ;            2 - XGA monitor is high-rez - capable of 1024x768
  21. ;            3 - XGA adapter has 1MB of RAM
  22. ;            4 - XGA adapter is in a dual-monitor setup
  23. ;        (IE, return code of 7 means XGA adapter with 512K of RAM
  24. ;        connected to a high-rez color monitor in a single-
  25. ;        monitor setup)
  26. ;
  27. ;    int xga_mode(int mode)
  28. ;        mode =    0 to enter normal VGA text mode (BIOS mode 3)
  29. ;            1 to enter 132-col VGA text mode
  30. ;            2 to enter 1024x768x256 graphics mode
  31. ;            3 to enter 1024x768x16 graphics mode
  32. ;            4 to enter 640x480x256 graphics mode
  33. ;            5 to enter 640x480x65536 graphics mode
  34. ;            6 to enter 800x600x16 graphics mode
  35. ;            7 to enter 800x600x256 graphics mode
  36. ;            8 to enter 800x600x65536 graphics mode
  37. ;        returns    0 on failure
  38. ;            1 on success
  39. ;        (NOTE!  You *must* use 'xga_mode(0)' to exit any of the
  40. ;        other modes and get back to standard VGA operation, even
  41. ;        on a dual-monitor (XGA & VGA) setup!  On a dual-monitor
  42. ;        setup, 'xga_mode(0)' leaves the XGA image intact, but
  43. ;        disables the XGA adapter's 64K aperture at A000:0000)
  44. ;
  45. ;    void xga_putpixel(int row, int col, int color)
  46. ;        writes pixel (row, col) using color
  47. ;        (all pixel counts start at 0, and [0][0] is in the UL corner)
  48. ;
  49. ;    int xga_getpixel(int row, int col)
  50. ;        returns    color of pixel at (row, col)
  51. ;        (all pixel counts start at 0, and [0][0] is in the UL corner)
  52. ;
  53. ;    void xga_putline(int row, int firstcol, int lastcol, char *pixels)
  54. ;        sends the line segment directly to the video
  55. ;        (all pixel counts start at 0, and [0][0] is in the UL corner)
  56. ;        (IE, xga_putline(3,7,12,*pixels) sends pixel[0] thru pixel[5]
  57. ;        to the 8th thru 13th pixel in the fourth row)
  58. ;
  59. ;    void xga_getline(int row, int firstcol, int lastcol, char *pixels)
  60. ;        reads the line segment directly from the video
  61. ;        (all pixel counts start at 0, and [0][0] is in the UL corner)
  62. ;        (IE, xga_putline(3,7,12,*pixels) fills pixel[0] thru pixel[5]
  63. ;        from the 8th thru 13th pixel in the fourth row)
  64. ;
  65. ;    void xga_setpalette(char *palette)
  66. ;        where 'palette' points to a 768-byte array of RGB values
  67. ;            (values from 0-255, not the VGA's internal 0-63!)
  68. ;
  69.  
  70.     .MODEL    medium,c
  71.  
  72.  
  73.     .DATA
  74.  
  75. public        xga_isinmode        ; (only public for Fractint purposes)
  76. public        xga_clearvideo        ; (only public for Fractint purposes)
  77.  
  78. xga_pos_base    dw    0        ; MCA Pos Base value
  79. xga_cardid    dw    0        ; MCA Card ID value
  80. xga_reg_base    dw    -1        ; XGA IO Reg Base (-1 means dunno yet)
  81. xga_1mb        dd    0        ; XGA 1MB aperture address
  82. xga_4mb        dd    0        ; XGA 4MB aperture address
  83. xga_result    dw    0        ; XGA_detect result code
  84. xga_isinmode    dw    0        ; XGA is in this mode right now
  85. xga_iscolors    dw    0        ; XGA using this many colors (0=64K)
  86. xga_clearvideo    db    0        ; set to 80h to prevent video-clearing
  87. xga_dotwrite    dw    0        ; write-a-dot routine:    mode-specific
  88. xga_dotread     dw    0        ; read-a-dot routine:    mode-specific
  89. xga_linewrite    dw    0        ; write-a-line routine: mode-specific
  90. xga_lineread    dw    0        ; read-a-line routine: mode-specific
  91. xga_curbk    dw    0        ; bank number
  92. xga_xdots    dw    0        ; bytes per scan line
  93. xga_linelen    dw    0        ; line segment length
  94. xga_offset    dw    0        ; line segment offset
  95.  
  96.     .CODE
  97.  
  98. ;        Graphics mode setup values
  99. ;        (the first two entries in each line 
  100. ;        indicate where the table values are to be stored)
  101. ;
  102. ;        1024x768x256 vvv
  103. ;        1024x768x16  -----vvvv
  104. ;        640x480x256  -----------vvvv
  105. ;        640x480x65536 ----------------vvvv
  106. ;        800x600x16   -----------------------vvvv
  107. ;        800x600x256  -----------------------------vvvv
  108. ;        800x600x65536 ----------------------------------vvvv
  109.  
  110. xga_twidth dw    9                    ; width of these tables
  111.  
  112. xga_requir dw      0,    0,  0dh,  05h,  01h,  09h,  01h,  01h,  09h    ; adapter requirements
  113. xga_colors dw       0,    0,  256,   16,  256,    0,   16,  256,    0    ; 0 means 64K colors
  114. xga_swidth dw      0,    0, 1024,  512,  640, 1280,  400,  800, 1600    ; bytes / scan line
  115.  
  116. xga_val    db    004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; interrupt enable
  117.     db    005h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; interrupt status
  118.     db    000h, 000h, 004h, 004h, 004h, 004h, 004h, 004h, 004h    ; operating mode
  119.     db    00ah, 064h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; palette mask
  120.     db    001h, 000h, 001h, 001h, 001h, 001h, 001h, 001h, 001h    ; vid mem aper cntl
  121.     db    008h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; vid mem aper indx
  122.     db    006h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; virt mem ctl
  123.     db    009h, 000h, 003h, 002h, 003h, 004h, 002h, 003h, 004h    ; mem access mode
  124.     db    00ah, 050h, 001h, 001h, 001h, 001h, 001h, 001h, 001h    ; disp mode 1
  125.     db    00ah, 050h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; disp mode 1
  126.     db    00ah, 010h, 09dh, 09dh, 063h, 063h, 088h, 088h, 088h    ; horiz tot lo.
  127.     db    00ah, 011h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; horiz tot hi.
  128.     db    00ah, 012h, 07fh, 07fh, 04fh, 04fh, 063h, 063h, 063h    ; hor disp end lo
  129.     db    00ah, 013h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor disp end hi
  130.     db    00ah, 014h, 07fh, 07fh, 04fh, 04fh, 063h, 063h, 063h    ; hor blank start lo
  131.     db    00ah, 015h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor blank start hi
  132.     db    00ah, 016h, 09dh, 09dh, 063h, 063h, 088h, 088h, 088h    ; hor blank end lo
  133.     db    00ah, 017h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor blank end hi
  134.     db    00ah, 018h, 087h, 087h, 055h, 055h, 06ah, 06ah, 06ah    ; hor sync start lo
  135.     db    00ah, 019h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor sync start hi
  136.     db    00ah, 01ah, 09ch, 09ch, 061h, 061h, 084h, 084h, 084h    ; hor sync end lo
  137.     db    00ah, 01bh, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor sync end hi
  138.     db    00ah, 01ch, 040h, 040h, 000h, 000h, 000h, 000h, 000h    ; hor sync pos
  139.     db    00ah, 01eh, 004h, 004h, 000h, 000h, 000h, 000h, 000h    ; hor sync pos
  140.     db    00ah, 020h, 030h, 030h, 00ch, 00ch, 086h, 086h, 086h    ; vert tot lo
  141.     db    00ah, 021h, 003h, 003h, 002h, 002h, 002h, 002h, 002h    ; vert tot hi
  142.     db    00ah, 022h, 0ffh, 0ffh, 0dfh, 0dfh, 057h, 057h, 057h    ; vert disp end lo
  143.     db    00ah, 023h, 002h, 002h, 001h, 001h, 002h, 002h, 002h    ; vert disp end hi
  144.     db    00ah, 024h, 0ffh, 0ffh, 0dfh, 0dfh, 057h, 057h, 057h    ; vert blank start lo
  145.     db    00ah, 025h, 002h, 002h, 001h, 001h, 002h, 002h, 002h    ; vert blank start hi
  146.     db    00ah, 026h, 030h, 030h, 00ch, 00ch, 086h, 086h, 086h    ; vert blank end lo
  147.     db    00ah, 027h, 003h, 003h, 002h, 002h, 002h, 002h, 002h    ; vert blank end hi
  148.     db    00ah, 028h, 000h, 000h, 0eah, 0eah, 058h, 058h, 058h    ; vert sync start lo
  149.     db    00ah, 029h, 003h, 003h, 001h, 001h, 002h, 002h, 002h    ; vert sync start hi
  150.     db    00ah, 02ah, 008h, 008h, 0ech, 0ech, 06eh, 06eh, 06eh    ; vert sync end
  151.     db    00ah, 02ch, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; vert line comp lo
  152.     db    00ah, 02dh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; vert line comp hi
  153.     db    00ah, 036h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; sprite cntl
  154.     db    00ah, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; start addr lo
  155.     db    00ah, 041h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; start addr me
  156.     db    00ah, 042h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; start addr hi
  157.     db    00ah, 043h, 080h, 040h, 050h, 0a0h, 032h, 064h, 0c8h    ; pixel map width lo
  158.     db    00ah, 044h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; pixel map width hi
  159.     db    00ah, 054h, 00dh, 00dh, 000h, 000h, 001h, 001h, 001h    ; clock sel
  160.     db    00ah, 051h, 003h, 002h, 003h, 004h, 002h, 003h, 004h    ; display mode 2
  161.     db    00ah, 070h, 000h, 000h, 000h, 000h, 080h, 080h, 080h    ; ext clock sel
  162.     db    00ah, 050h, 00fh, 00fh, 0c7h, 0c7h, 007h, 007h, 007h    ; display mode 1
  163.     db    00ah, 055h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Border Color
  164.     db    00ah, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pal Lo
  165.     db    00ah, 061h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pal hi
  166.     db    00ah, 062h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pre Lo
  167.     db    00ah, 063h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pre hi
  168.     db    00ah, 064h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; Palette Mask
  169.     db    0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; end of the list
  170.  
  171. xga_newbank    proc            ; XGA-specific bank-switching routine
  172.     cmp    xga_isinmode,2        ; are we in an XGA-specific mode?
  173.     jl    return            ;  nope.  bail out.
  174.     mov    xga_curbk,ax        ; save the new current bank value
  175.     mov    dx,xga_reg_base        ; Select Page
  176.     add    dx,08h
  177.     out    dx,al            ; assumes bank number is in al
  178. return:    ret
  179. xga_newbank    endp
  180.  
  181. xga_nullroutine    proc    near        ; "do-nothing" placeholder routine
  182.     mov    ax,0
  183.     ret
  184. xga_nullroutine    endp
  185.  
  186. xga_normalinewrite    proc    near    ; slow, generic line-write routine
  187. normal_line1:
  188.     push    ax            ; save stop col
  189.     mov    al,[si]         ; retrieve the color
  190.     cmp    xga_iscolors,0        ; 64K-color mode?
  191.     jne    normal_line2
  192.     mov    ax,[si]            ; yup - adjust
  193.     inc    si
  194. normal_line2:
  195.     push    cx            ; save the counter around the call
  196.     push    dx            ; save column around the call
  197.     push    si            ; save the pointer around the call also
  198.     call    xga_dotwrite        ; write the dot via the approved method
  199.     pop    si            ; restore the pointer
  200.     pop    dx            ; restore the column
  201.     pop    cx            ; restore the counter
  202.     inc    si            ; bump it up
  203.     inc    cx            ; bump it up
  204.     pop    ax            ; retrieve number of dots
  205.     cmp    cx,ax            ; more to go?
  206.     jl    normal_line1        ; yup.    do it.
  207.     ret
  208. xga_normalinewrite    endp
  209.  
  210. xga_normalineread    proc    near    ; slow, generic read-line routine
  211.     mov    bx,0a000h
  212.     mov    es,bx
  213. normal_lineread1:
  214.     push    ax            ; save stop col
  215.     push    cx            ; save the counter around the call
  216.     push    dx            ; save column around the call
  217.     push    di            ; save the pointer around the call also
  218.     call    xga_dotread         ; read the dot via the approved method
  219.     pop    di            ; restore the pointer
  220.     pop    dx            ; restore the column
  221.     pop    cx            ; restore the counter
  222.     mov    bx,di            ; locate the actual pixel color
  223.     mov    [bx],al         ; retrieve the color
  224.     cmp    xga_iscolors,0        ; 64K-color mode?
  225.     jne    normal_line2
  226.     mov    [bx],ax            ; yup - adjust
  227.     inc    di
  228. normal_line2:
  229.     inc    di            ; bump it up
  230.     inc    cx            ; bump it up
  231.     pop    ax            ; retrieve number of dots
  232.     cmp    cx,ax            ; more to go?
  233.     jle    normal_lineread1    ; yup.    do it.
  234.     ret
  235. xga_normalineread    endp
  236.  
  237. xga_sameseg    proc    near        ; line segment support
  238.     cmp    xga_iscolors,0        ; 64K-color mode?
  239.     jne    xga_sk1
  240.     add    ax,ax            ; two bytes / pixel
  241.     add    cx,cx
  242. xga_sk1:
  243.     mov    bx,ax            ; calculate the line segment len
  244.     sub    bx,cx
  245.     mov    xga_linelen,bx
  246.     mov    ax,xga_xdots        ; calculate the first pixel bank
  247.     mul    dx
  248.     add    ax,cx
  249.     adc    dx,0
  250.     mov    bx,dx            ; save the bank address
  251.     mov    xga_offset,ax        ; save the destination
  252.     add    ax,xga_linelen        ; calculate the last pixel bank
  253.     adc    dx,0
  254.     cmp    dx,bx            ; same bank?
  255.     jne    xga_sk2            ;  nope
  256.     mov    ax,dx            ; xga_newbank expects bank in al
  257.     call    far ptr xga_newbank
  258.     cmp    ax,ax            ; set flag: same bank
  259. xga_sk2:ret
  260. xga_sameseg    endp
  261.  
  262. xga_16linewrite    proc    near        ; 16-color Line Write
  263.     mov    bx,ax            ; calculate the # of columns
  264.     sub    bx,cx
  265.     mov    ax,xga_xdots        ; this many dots / line
  266.     mul    dx            ; times this many lines - ans in dx:ax
  267.     push    cx            ; save the X-value for a tad
  268.     shr    cx,1            ; and adjust for two bits per pixel
  269.     add    ax,cx            ; plus this many x-dots
  270.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  271.     mov    di,ax            ; save offset in DI
  272.     pop    cx            ; restore the X-value
  273.     mov    ax,dx            ; xga_newbank expects bank in al
  274. new_bank:
  275.     call    far ptr xga_newbank
  276. same_bank:
  277.     mov    ah,es:[di]        ; grab the old byte value
  278.     mov    al,[si]            ; and the new color value
  279.     and    al,0fh            ; isolate the bits we want
  280.     test    cx,1            ; odd pixel address?
  281.     jnz    xga_sk1            ;  yup
  282.     and    ah,0f0h            ; isolate the low-order
  283.     jmp    short    xga_sk2
  284. xga_sk1:and    ah,0fh            ; isolate the high-order
  285.     shl    al,1
  286.     shl    al,1
  287.     shl    al,1
  288.     shl    al,1
  289. xga_sk2:or    al,ah            ; combine the two nibbles
  290.     mov    es:[di],al        ; write the dot
  291.     inc    si            ; increment the source addr
  292.     dec    bx            ; more to go?
  293.     jz    done            ; nope
  294.     inc    cx            ; next pixel
  295.     test    cx,1            ; odd pixel?
  296.     jnz    same_bank        ;  yup
  297.     inc    di            ; increment the destination
  298.     cmp    di,0            ; segment wrap?
  299.     jnz    same_bank        ;  nope
  300.     mov    ax,xga_curbk        ; update the bank cvalue
  301.     inc    ax
  302.     jmp    new_bank
  303. done:    ret
  304. xga_16linewrite        endp
  305.  
  306. xga_256linewrite    proc    near    ; 256-color, 64K color line write
  307.     push    dx            ; save a few registers
  308.     push    cx
  309.     push    ax
  310.     call    xga_sameseg
  311.     jne    slow            ; go slow if banks changed
  312.     mov    cx,xga_linelen        ; do it the fast way
  313.     mov    di,xga_offset
  314.     cld
  315.     shr    cx,1
  316.     rep    movsw
  317.     rcl    cx,1
  318.     rep    movsb
  319.     pop    ax            ; restore the registers
  320.     pop    cx
  321.     pop    dx
  322.     ret
  323. slow:    pop    ax            ; call the slow routine
  324.     pop    cx
  325.     pop    dx
  326.     call    xga_normalinewrite
  327.     ret
  328. xga_256linewrite    endp
  329.  
  330. xga_256lineread    proc    near        ; 256-color, 64K color line write
  331.     push    dx            ; save a few registers
  332.     push    cx
  333.     push    ax
  334.     call    xga_sameseg
  335.     jne    slow            ; go slow if banks changed
  336.     mov    cx,xga_linelen        ; do it the fast way
  337.     mov    si,xga_offset
  338.     push    ds
  339.     pop    es
  340.     mov    ax,0a000h
  341.     mov    ds,ax
  342.     cld
  343.     shr    cx,1
  344.     rep    movsw
  345.     rcl    cx,1
  346.     rep    movsb
  347.     push    es
  348.     pop    ds
  349.     pop    ax            ; restore the registers
  350.     pop    cx
  351.     pop    dx
  352.     ret
  353. slow:    pop    ax            ; call the slow routine
  354.     pop    cx
  355.     pop    dx
  356.     call    xga_normalineread
  357.     ret
  358. xga_256lineread    endp
  359.  
  360. xga_super256addr    proc near    ; can be put in-line but shared by
  361.                     ; read and write routines
  362.     clc                ; clear carry flag
  363.     push    ax            ; save this for a tad
  364.     mov    ax,xga_xdots        ; this many dots / line
  365.     mul    dx            ; times this many lines - ans in dx:ax
  366.     add    ax,cx            ; plus this many x-dots
  367.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  368.     mov    bx,ax            ; save this in BX
  369.     cmp    dx,xga_curbk        ; see if bank changed
  370.     je    same_bank        ; jump if old bank ok
  371.     mov    ax,dx            ; xga_newbank expects bank in al
  372.     call    far ptr xga_newbank
  373. same_bank:
  374.     pop    ax            ; restore AX
  375.     ret
  376. xga_super256addr    endp
  377.  
  378. xga_super64kaddr    proc near    ; can be put in-line but shared by
  379.                     ; read and write routines
  380.     clc                ; clear carry flag
  381.     push    ax            ; save this for a tad
  382.     mov    ax,xga_xdots        ; this many dots / line
  383.     mul    dx            ; times this many lines - ans in dx:ax
  384.     add    ax,cx            ; plus this many x-dots
  385.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  386.     add    ax,cx            ; plus this many x-dots
  387.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  388.     mov    bx,ax            ; save this in BX
  389.     cmp    dx,xga_curbk        ; see if bank changed
  390.     je    same_bank        ; jump if old bank ok
  391.     mov    ax,dx            ; xga_newbank expects bank in al
  392.     call    far ptr xga_newbank
  393. same_bank:
  394.     pop    ax            ; restore AX
  395.     ret
  396. xga_super64kaddr    endp
  397.  
  398. xga_super16addr    proc near        ; can be put in-line but shared by
  399.                     ; read and write routines
  400.     clc                ; clear carry flag
  401.     push    ax            ; save this for a tad
  402.     mov    ax,xga_xdots        ; this many dots / line
  403.     mul    dx            ; times this many lines - ans in dx:ax
  404.     push    cx            ; save the X-value for a tad
  405.     shr    cx,1            ; and adjust for two bits per pixel
  406.     add    ax,cx            ; plus this many x-dots
  407.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  408.     pop    cx            ; restore the X-value
  409.     mov    bx,ax            ; save this in BX
  410.     cmp    dx,xga_curbk        ; see if bank changed
  411.     je    same_bank        ; jump if old bank ok
  412.     mov    ax,dx            ; xga_newbank expects bank in al
  413.     call    far ptr xga_newbank
  414. same_bank:
  415.     pop    ax            ; restore AX
  416.     ret
  417. xga_super16addr    endp
  418.  
  419. xga_256write    proc near        ; XGA 256 colors write-a-dot
  420.     call    xga_super256addr    ; calculate address and switch banks
  421.     mov    es:[bx],al        ; write the dot
  422.     ret                ; we done.
  423. xga_256write    endp
  424.  
  425. xga_256read    proc near        ; XGA 256 colors read-a-dot
  426.     call    xga_super256addr    ; calculate address and switch banks
  427.     mov    al,es:[bx]        ; read the dot
  428.     mov    ah,0            ; convert to an int
  429.     ret                ; we done.
  430. xga_256read    endp
  431.  
  432. xga_64kwrite    proc near        ; XGA 256 colors write-a-dot
  433.     call    xga_super64kaddr    ; calculate address and switch banks
  434.     mov    es:[bx],ax        ; write the dot
  435.     ret                ; we done.
  436. xga_64kwrite    endp
  437.  
  438. xga_64kread    proc near        ; XGA 256 colors read-a-dot
  439.     call    xga_super64kaddr    ; calculate address and switch banks
  440.     mov    ax,es:[bx]        ; read the dot
  441.     ret                ; we done.
  442. xga_64kread    endp
  443.  
  444. xga_16write    proc near        ; XGA 256 colors write-a-dot
  445.     call    xga_super16addr        ; calculate address and switch banks
  446.     mov    ah,es:[bx]        ; grab the old byte value
  447.     and    al,0fh            ; isolate the bits we want
  448.     test    cx,1            ; odd pixel address?
  449.     jnz    xga_sk1            ;  yup
  450.     and    ah,0f0h            ; isolate the low-order
  451.     jmp    short    xga_sk2
  452. xga_sk1:and    ah,0fh            ; isolate the high-order
  453.     shl    al,1
  454.     shl    al,1
  455.     shl    al,1
  456.     shl    al,1
  457. xga_sk2:or    al,ah            ; combine the two nibbles
  458.     mov    es:[bx],al        ; write the dot
  459.     ret                ; we done.
  460. xga_16write    endp
  461.  
  462. xga_16read    proc near        ; XGA 256 colors read-a-dot
  463.     call    xga_super16addr        ; calculate address and switch banks
  464.     mov    al,es:[bx]        ; read the dot
  465.     test    cx,1            ; odd number of pixels?
  466.     jz    xga_sk1            ;  nope
  467.     shr    ax,1            ; adjust for odd pixel count
  468.     shr    ax,1
  469.     shr    ax,1
  470.     shr    ax,1
  471. xga_sk1:and    ax,0fh            ; isolate the byte value
  472.     ret                ; we done.
  473. xga_16read    endp
  474.  
  475. xga_clear    proc    uses es si di    ; clear the XGA memory
  476.     cmp    xga_clearvideo,0    ; should we really do this?
  477.     jne    return            ;  nope.  skip it.
  478.     mov    bx,xga_result        ; find out how much memory we have
  479.     and    bx,08h            ;  in 64K pages
  480.     add    bx,08h
  481.     mov    ax,0a000h        ; set up to clear 0a0000-0affff
  482.     push    ax
  483.     pop    es
  484. xloop:    mov    ax,bx            ; initialize the bank addr
  485.     call    xga_newbank
  486.     mov    ax,0
  487.     mov    cx,16384        ; clear out 32K
  488.     mov    di,0
  489.     rep    stosw
  490.     mov    cx,16384        ; clear out 32K
  491.     rep    stosw
  492.     dec    bx            ; another page?
  493.     cmp    bx,0
  494.     jge    xloop
  495. return:    ret
  496. xga_clear    endp
  497.  
  498. xga_setpalette    proc    uses es si di, palette:word    ; set the XGA palette
  499.     cmp    xga_isinmode,2        ; are we in an XGA graphics mode?
  500.     jl    return            ;  nope
  501.  
  502.     mov    dx,xga_reg_base        ; wait for a retrace
  503.     add    dx,5
  504.     mov    al,1            ; clear the start-of-blanking
  505.     out    dx,al
  506. bloop:    in    al,dx
  507.     test    al,01h            ; blanking started?
  508.     jz    bloop            ;  nope - try again
  509.  
  510.     mov    dx,xga_reg_base        ; set up for a palette load
  511.     add    dx,0ah
  512.     mov    ax,0064h        ; make invisible
  513.     out    dx,ax
  514.     mov    ax,0055h        ; border color
  515.     out    dx,ax
  516.     mov    ax,0066h        ; palette mode
  517.     out    dx,ax
  518.     mov    ax,0060h        ; start at palette 0
  519.     out    dx,ax
  520.     mov    ax,0061h
  521.     out    dx,ax
  522.  
  523.     mov    si,palette
  524.     mov    cx,768
  525.     mov    ax,065h            ; palette update
  526.     out    dx,al
  527.     inc    dx            ; palette data
  528. .186
  529.     rep    outsb            ; update all registers at once
  530. .8086
  531.     dec    dx
  532.  
  533.     mov    ax,0ff64h        ; make visible
  534.     out    dx,ax
  535.  
  536. return:    ret
  537. xga_setpalette    endp
  538.  
  539. xga_detect    proc    uses es di si
  540.  
  541.     cmp    xga_reg_base,-2        ; has the XGA detector already failed?
  542.     jne    xga_sk1            ; ne = not yet
  543.     jmp    xga_notfound        ; e = yes, fail again
  544. xga_sk1:cmp    xga_reg_base,-1        ; have we already found the XGA?
  545.     je    xga_loc            ; e = no
  546.     jmp    xga_found        ; yes, process it
  547.  
  548. xga_loc:mov    ah,35h            ; DOS get interrupt vector
  549.     mov    al,15h            ; Int 15h
  550.     int    21h            ; returns vector in es:bx
  551.     mov    ax,es            ; segment part
  552.     or    ax,bx            ; undefined vector?
  553.     jnz    xga_sk2            ; nz = no, OK so far
  554.     jmp    xga_notfound        ; z = yes - not an MCA machine
  555. xga_sk2:mov    dx,-1            ; start with an invalid POS address
  556.     mov    ax,0c400h        ; look for POS base address
  557.     int    15h            ;  (Microchannel machines only)
  558.     jnc    xga_sk3            ; nc = success
  559.     jmp    xga_notfound        ; error - not an MC machine
  560. xga_sk3:mov    xga_pos_base,dx        ; save pos_base_address
  561.     xor    cx,cx            ; check all MCA slots & motherboard
  562.     cmp    dx,-1            ; do we have a good POS?
  563.     jne    xga_lp1            ; ne = yes, proceed with MCA checks
  564.     jmp    xga_notfound        ; no, fail
  565.  
  566. xga_lp1:cli                ; no interrupts, please
  567.     cmp    cx,0            ; treat the motherboard differently?
  568.     jne    xga_sk4            ; ne = yes
  569.     mov    al,0dfh            ; enable the motherboard for setup
  570.     mov    dx,94h
  571.     out    dx,al
  572.     jmp    short xga_sk5
  573. xga_sk4:mov    ax,0c401h        ; enable an MCA slot for setup
  574.     mov    bx,cx            ;  this slot
  575.     int    15h
  576. xga_sk5:mov    dx,xga_pos_base        ; get pos record for the slot ID
  577.     in    ax,dx
  578.     mov    xga_cardid,ax
  579.     add    dx,2            ; compute IO Res Base
  580.     in    al,dx            ;  get POS data byte1
  581.     mov    byte ptr xga_1mb,al    ;   save it temporarily
  582.     inc    dx            ; switch to byte 2
  583.     in    al,dx            ;  get POS data
  584.     mov    byte ptr xga_1mb+1,al    ;   save it temporarily
  585.     inc    dx            ; switch to byte 3
  586.     in    al,dx            ;  get POS data
  587.     mov    byte ptr xga_1mb+2,al    ;   save it temporarily
  588.     inc    dx            ; switch to byte 4
  589.     in    al,dx            ;  get POS data
  590.     mov    byte ptr xga_1mb+3,al    ;   save it temporarily
  591.     cmp    cx,0            ; treat the motherboard differently
  592.     jne    xga_sk6            ; ne = yes
  593.     mov    al,0ffh            ; enable the motherboard for normal
  594.     out    094h,al
  595.     jmp    short xga_sk7
  596. xga_sk6:mov    ax,0c402h        ; enable the MCA slot for normal
  597.     mov    bx,cx            ;  this slot
  598.     int    15h
  599. xga_sk7:sti                ; interrupts on again
  600.  
  601.     mov    ax,xga_cardid        ; is an XGA adapter on this slot?
  602.     cmp    ax,08fd8h
  603.     jae    xga_sk8            ; ae = yes
  604.     jmp    xga_lp2            ; try another slot
  605. xga_sk8:cmp    ax,08fdbh        ; still within range?
  606.     jbe    xga_sk9            ; be = yes
  607.     jmp    xga_lp2            ; no, try another slot
  608.  
  609. xga_sk9:mov    al,byte ptr xga_1mb    ;  restore POS data byte 1
  610.     and    ax,0eh            ;  muck about with it to get reg base
  611.     shl    ax,1
  612.     shl    ax,1
  613.     shl    ax,1
  614.     add    ax,2100h
  615.     mov    xga_reg_base,ax
  616.     mov    dx,xga_reg_base        ; is there a monitor on this slot?
  617.     add    dx,0ah
  618.     mov    al,052h
  619.     out    dx,al
  620.     mov    dx,xga_reg_base
  621.     add    dx,0bh
  622.     in    al,dx
  623.     and    al,0fh
  624.     cmp    al,00h            ; illegal value, returned under Win 3.0
  625.     je    xga_lp2
  626.     cmp    al,0fh
  627.     jne    xga_isthere        ; ne = yes
  628.  
  629. xga_lp2:inc    cx            ; try another adapter?
  630.     cmp    cx,9            ; done all slots?
  631.     ja    xga_ska            ; a = yes
  632.     jmp    xga_lp1            ; no, try another slot
  633.  
  634. xga_ska:jmp    xga_notfound        ; forget it - no XGA here
  635.  
  636. xga_isthere:
  637.     and    ax,06h            ; strip off the low & high bit
  638.     xor    ax,05h            ; reverse the 3rd & low bits
  639.     mov    xga_result,ax        ; save the result flag
  640.  
  641.     mov    dx,xga_reg_base        ; is this XGA in VGA mode?
  642.     in    al,dx
  643.     test    al,1
  644.     jnz    xga_skb            ; nz = yes - single-monitor setup
  645.     or    xga_result,10h        ;  dual-monitor setup
  646. xga_skb:
  647.  
  648.     mov    ah,byte ptr xga_1mb+2    ; retrieve POS data byte 3
  649.     and    ax,0fe00h        ; eliminate the low-order bits
  650.     mov    bl,byte ptr xga_1mb    ; retrieve POS data byte 1
  651.     and    bx,0eh            ; strip it down to the IODA
  652.     mov    cx,5            ; shift it up 5 bits
  653.     shl    bx,cl
  654.     or    ax,bx            ; compute the 4MB aperture value
  655.     mov    word ptr xga_4mb+2,ax    ; save the result
  656.  
  657.     mov    al, byte ptr xga_1mb+3    ; retrieve POS data byte 4
  658.     and    ax,0fh            ; select the 1MB aperture bits
  659.     mov    cx,4            ; shift it up 4 bits
  660.     shl    ax,cl
  661.     mov    word ptr xga_1mb+2,ax    ; save the result
  662.     mov    ax,0
  663.     mov    word ptr xga_1mb,ax 
  664.  
  665.     mov    dx,xga_reg_base        ; Interrupt Disable
  666.     add    dx,4
  667.     xor    al,al
  668.     out    dx,al
  669.  
  670.     mov    dx,xga_reg_base        ; Switch to Extended Mode
  671. ;;    add    dx,00h
  672.     mov    al,4
  673.     out    dx,al
  674.  
  675.     mov    dx,xga_reg_base        ; Aperture Control
  676.     add    dx,01h
  677.     mov    al,1
  678.     out    dx,al
  679.  
  680.     mov    dx,xga_reg_base        ; disable Palette Mask
  681.     add    dx,0ah
  682.     mov    ax,0064h
  683.     out    dx,ax
  684.  
  685.     mov    xga_isinmode,2        ; pretend we're already in graphics
  686.     mov    al,12            ; select page 12
  687.     call    xga_newbank
  688.  
  689.     push    es            ; see if this page has any memory
  690.     mov    ax,0a000h
  691.     push    ax
  692.     pop    es
  693.     mov    ah,000a5h
  694.     mov    es:0,al
  695.     mov    es:1,ah
  696.     cmp    es:0,al
  697.     jne    xga_512
  698.     add    xga_result,8        ; 1MB RAM found
  699. xga_512:pop    es
  700.  
  701.     mov    al,0            ; select page 0
  702.     call    xga_newbank
  703.     mov    xga_isinmode,0        ; replace the "in-graphics" flag
  704.  
  705.     mov    dx,xga_reg_base        ; Palette Mask
  706.     add    dx,0ah
  707.     mov    ax,0ff64h
  708.     out    dx,ax
  709.  
  710.     test    xga_result,10h        ; dual monitor setup?
  711.     jnz    xga_found        ;  yup - don't restore as a VGA
  712.  
  713.     mov    dx,xga_reg_base        ; Switch to VGA Mode
  714. ;;    add    dx,00h
  715.     mov    al,1
  716.     out    dx,al
  717.  
  718.     mov    dx,03c3h        ; Enable VGA Address Code
  719.     mov    al,1
  720.     out    dx,al
  721.  
  722.     jmp    short    xga_found
  723.  
  724. xga_notfound:
  725.     mov    xga_reg_base,-2        ; set failure flag
  726. xga_found:
  727.     mov    ax,xga_result        ; return the result
  728.     ret
  729.  
  730. xga_detect    endp
  731.  
  732. xga_mode    proc    uses es di si, mode:word
  733.  
  734.     mov    ax, offset xga_nullroutine    ; null out the pixel rtns
  735.     mov    xga_dotwrite,ax
  736.     mov    xga_dotread,ax
  737.     mov    ax,offset xga_normalinewrite
  738.     mov    xga_linewrite,ax
  739.     mov    ax,offset xga_normalineread
  740.     mov    xga_lineread,ax
  741.     mov    xga_curbk,-1        ; preload impossible bank number
  742.  
  743.     call    xga_detect        ; is an XGA adapter present?
  744.     cmp    ax,0
  745.     jne    whichmode
  746.     jmp    nope            ;  nope - fail right now.
  747. whichmode:
  748.     mov    bx,mode
  749.     cmp    bx,xga_twidth        ; mode number out of range?
  750.     jb    whichmode0
  751.     jmp    nope            ;  yup - fail right now.
  752. whichmode0:
  753.     cmp    mode,0            ; 80-col VGA text mode?
  754.     jne    whichmode1
  755.     jmp    mode_0            ;  yup
  756. whichmode1:
  757.     cmp    mode,1            ; 132-col VGA text mode?
  758.     jne    whichmode2
  759.     jmp    mode_1            ;  yup
  760. whichmode2:
  761.     mov    bx,mode            ; locate the table entries
  762.     add    bx,mode
  763.     mov    dx,xga_requir[bx]    ; does our setup support this mode?
  764.     and    al,dl
  765.     cmp    al,dl
  766.     je    whichmode3
  767.     jmp    nope            ;  nope
  768. whichmode3:
  769.     mov    dx,xga_swidth[bx]    ; collect and save the scan-line length
  770.     mov    xga_xdots,dx
  771.     mov    dx,xga_colors[bx]    ; how many colors do we have?
  772.     mov    xga_iscolors,dx        ; save this
  773.     cmp    dx,256            ; 256-color mode?
  774.     je    whichmode4
  775.     cmp    dx,0            ; 64K-color mode?
  776.     je    whichmode5
  777.                     ; 16-color modes
  778.     mov    bx, offset xga_16read
  779.     mov    xga_dotread,bx
  780.     mov    bx, offset xga_16write
  781.     mov    xga_dotwrite,bx
  782.     mov    bx, offset xga_16linewrite
  783.     mov    xga_linewrite,bx
  784.     mov    bx,offset xga_normalineread
  785.     mov    xga_lineread,bx
  786.     jmp    mode_3
  787. whichmode4:                ; 256-color modes
  788.     mov    bx, offset xga_256read
  789.     mov    xga_dotread,bx
  790.     mov    bx, offset xga_256write
  791.     mov    xga_dotwrite,bx
  792.     mov    bx, offset xga_256linewrite
  793.     mov    xga_linewrite,bx
  794.     mov    bx, offset xga_256lineread
  795.     mov    xga_lineread,bx
  796.     jmp    mode_3
  797. whichmode5:                ; 64K-color modes
  798.     mov    bx, offset xga_64kread
  799.     mov    xga_dotread,bx
  800.     mov    bx, offset xga_64kwrite
  801.     mov    xga_dotwrite,bx
  802.     mov    bx, offset xga_256linewrite
  803.     mov    xga_linewrite,bx
  804.     mov    bx, offset xga_256lineread
  805.     mov    xga_lineread,bx
  806.     jmp    mode_3
  807.  
  808. mode_3:                    ; common graphics mode routines
  809.     mov    dx,03c3h        ; Enable VGA Address Code
  810.     mov    al,1
  811.     out    dx,al
  812.  
  813.     mov    si,offset xga_val    ; point to start of values table
  814.     mov    bx,mode            ; use mode as an offset
  815. model1: mov    dx,xga_reg_base        ; get the base pointer
  816.     mov    ah,0            ; get the increment
  817.     mov    al,cs:0[si]
  818.     cmp    al,0ffh            ; end of the table?
  819.     je    model2            ;  yup
  820.     add    dx,ax
  821.     cmp    al,0ah            ; check for access type
  822.     je    modsk2
  823.     mov    al,cs:0[si+bx]        ; get the value and OUT it
  824.     out    dx,al
  825.     jmp    short modsk3
  826. modsk2:    mov    al,cs:1[si]        ; get the value and OUT it
  827.     mov    ah,cs:0[si+bx]
  828.     out    dx,ax
  829. modsk3:    add    si,xga_twidth        ; try another table entry
  830.     jmp    short model1
  831. model2:
  832.  
  833.     mov    xga_isinmode,2        ; pretend we're already in graphics
  834.     call    xga_clear        ; clear out the memory
  835.     mov    xga_curbk,-1        ; reset the bank counter
  836.  
  837.     mov    dx,xga_reg_base        ; set up for final loads
  838.     add    dx,0ah
  839.     cmp    xga_iscolors,0        ; "true color" mode?
  840.     jne    modsk4            ; nope - skip the funny palette load
  841.  
  842.     mov    ax,0064h        ; make invisible
  843.     out    dx,ax
  844.     mov    ax,8055h        ; border color
  845.     out    dx,ax
  846.     mov    ax,0066h        ; palette mode
  847.     out    dx,ax
  848.     mov    ax,0060h        ; start at palette 0
  849.     out    dx,ax
  850.     mov    ax,0061h        ; ""
  851.     out    dx,ax
  852.  
  853.     mov    cx,0            ; ready to update the palette
  854.     mov    al,065h            ; palette update
  855.     out    dx,al
  856.     inc    dx            ; palette data
  857. model3:    mov    al,0            ; zero out the...
  858.     out    dx,al            ;  red value
  859.     out    dx,al            ;  and the green value
  860.     mov    al,cl            ; klooge up the blue value
  861.     and    al,1fh            ; convert to 1,2,...1f
  862.     shl    al,1            ; convert to 2,4,...3e
  863.     shl    al,1            ; convert to 4,8,...7c
  864.     shl    al,1            ; convert to 8,16,..fd
  865.     out    dx,al            ; blue value
  866.     inc    cx            ; another palette value to go?
  867.     cmp    cx,128
  868.     jb    model3
  869.     dec    dx            ; back to normal
  870.  
  871. modsk4:    mov    ax,0ff64h        ; make the palette visible
  872.     out    dx,ax
  873.     jmp    ok
  874.  
  875. mode_0:                    ; Set 80 column mode
  876.     mov    dx,xga_reg_base        ; Aperture Control
  877.     add    dx,01h
  878.     xor    al,al            ; (disable the XGA 64K aperture)
  879.     out    dx,al
  880.  
  881.     mov    dx,xga_reg_base        ; Interrupt Disable
  882.     add    dx,4
  883.     xor    al,al
  884.     out    dx,al
  885.  
  886.     mov    dx,xga_reg_base        ; Clear Interrupts
  887.     add    dx,5
  888.     mov    al,0ffh
  889.     out    dx,al
  890.  
  891.     test    xga_result,10h        ; dual monitor setup?
  892.     jz    mode_0a
  893.     jmp    nope            ;  yup - don't restore as a VGA
  894. mode_0a:
  895.  
  896.     mov    dx,xga_reg_base        ; Palette Mask
  897.     add    dx,0ah
  898.     mov    ax,0ff64h        ; (Disable the XGA palette)
  899.     out    dx,ax
  900.  
  901.     mov    dx,xga_reg_base        ; Enable VFB, Prepare for Reset
  902.     add    dx,0ah
  903.     mov    ax,1550h
  904.     out    dx,ax
  905.  
  906.     mov    dx,xga_reg_base        ; Enable VFB, reset CRTC
  907.     add    dx,0ah
  908.     mov    ax,1450h
  909.     out    dx,ax
  910.  
  911.     mov    dx,xga_reg_base        ; Normal Scale Factors
  912.     add    dx,0ah
  913.     mov    ax,0051h
  914.     out    dx,ax
  915.  
  916.     mov    dx,xga_reg_base        ; Select VGA Oscillator
  917.     add    dx,0ah
  918.     mov    ax,0454h
  919.     out    dx,ax
  920.  
  921.     mov    dx,xga_reg_base        ; Ext Oscillator (VGA)
  922.     add    dx,0ah
  923.     mov    ax,7f70h
  924.     out    dx,ax
  925.  
  926.     mov    dx,xga_reg_base        ; Ensure no Vsynch Interrupts
  927.     add    dx,0ah
  928.     mov    ax,202ah
  929.     out    dx,ax
  930.  
  931.     mov    dx,xga_reg_base        ; Switch to VGA Mode
  932. ;;    add    dx,00h
  933.     mov    al,1
  934.     out    dx,al
  935.  
  936.     mov    dx,03c3h        ; Enable VGA Address Code
  937.     mov    al,1
  938.     out    dx,al
  939.  
  940.     mov    ax,1202h        ; select 400 scan lines
  941.     mov    bl,30h
  942.     int    10h
  943.     mov    ax,0+3            ; set video mode 3
  944.     or    al,xga_clearvideo    ; (might supress video-clearing)
  945.     int    10h
  946.  
  947.     jmp    ok            ; we're done
  948.  
  949. mode_1:                    ; 132-col VGA text mode
  950.     test    xga_result,10h        ; dual monitor setup?
  951.     jz    mode_1a
  952.     jmp    nope            ;  yup - don't restore as a VGA
  953. mode_1a:
  954.     mov    dx,xga_reg_base
  955.     add    dx,0ah
  956.     mov    ax,1550h        ; prepare CRTC for Reset
  957.     out    dx,ax
  958.     mov    ax,1450h        ; Reset CRTC
  959.     out    dx,ax
  960.     mov    ax,0454h        ; Select VGA Oscillator
  961.     out    dx,ax
  962.     mov    ax,1202h        ; select 400 scan lines
  963.     mov    bl,30h
  964.     int    10h
  965.     mov    ax,0+3            ; set video mode 3
  966.     or    al,xga_clearvideo    ; (might supress video-clearing)
  967.     int    10h
  968.  
  969.     mov    dx,xga_reg_base        ; Prepare CRTC for Reset
  970.     add    dx,0ah
  971.     mov    al,50h
  972.     out    dx,al
  973.     inc    dx
  974.     in    al,dx
  975.     or    al,1
  976.     out    dx,al
  977.  
  978.     mov    dx,xga_reg_base        ; Prepare CRTC for Reset
  979.     add    dx,0ah
  980.     mov    al,50h
  981.     out    dx,al
  982.     inc    dx
  983.     in    al,dx
  984.     and    al,0fdh
  985.     out    dx,al
  986.  
  987.     mov    dx,xga_reg_base        ; Reset CRTC
  988.     add    dx,0ah
  989.     mov    al,50h
  990.     out    dx,al
  991.     inc    dx
  992.     in    al,dx
  993.     and    al,0fch
  994.     out    dx,al
  995.  
  996.     mov    dx,xga_reg_base        ; 132 column text mode
  997.     mov    al,3
  998.     out    dx,al
  999.  
  1000.     mov    dx,xga_reg_base        ; 132 column clock freq select
  1001.     add    dx,0ah
  1002.     mov    ax,0154h
  1003.     out    dx,ax
  1004.     mov    ax,8070h        ; Select internal 132 col clock
  1005.     out    dx,ax
  1006.  
  1007.     mov    dx,xga_reg_base        ; Disable VFB
  1008.     add    dx,0ah
  1009.     mov    al,50h
  1010.     out    dx,al
  1011.     inc    dx
  1012.     in    al,dx
  1013.     and    al,0efh
  1014.     out    dx,al
  1015.  
  1016.     mov    dx,03d4h        ; Enable VGA CRTC reg update
  1017.     mov    ax,11h
  1018.     out    dx,al
  1019.     inc    dx
  1020.     in    al,dx
  1021.     and    al,7fh
  1022.     out    dx,al
  1023.  
  1024.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1025.     mov    ax,0            ; (I swear, that's what the manual
  1026.     out    dx,al            ; says...)
  1027.     inc    dx
  1028.     mov    ax,0a4h
  1029.     out    dx,al
  1030.  
  1031.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1032.     mov    ax,1
  1033.     out    dx,al
  1034.     inc    dx
  1035.     mov    ax,83h
  1036.     out    dx,al
  1037.  
  1038.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1039.     mov    ax,2
  1040.     out    dx,al
  1041.     inc    dx
  1042.     mov    ax,84h
  1043.     out    dx,al
  1044.  
  1045.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1046.     mov    ax,3
  1047.     out    dx,al
  1048.     inc    dx
  1049.     mov    ax,83h
  1050.     out    dx,al
  1051.  
  1052.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1053.     mov    ax,4
  1054.     out    dx,al
  1055.     inc    dx
  1056.     mov    ax,90h
  1057.     out    dx,al
  1058.  
  1059.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1060.     mov    ax,5
  1061.     out    dx,al
  1062.     inc    dx
  1063.     mov    ax,80h
  1064.     out    dx,al
  1065.  
  1066.     mov    dx,xga_reg_base        ; Variations on VGA CRTC synchs
  1067.     add    dx,0ah
  1068.     mov    ax,0a31ah
  1069.     out    dx,ax
  1070.     mov    ax,001bh
  1071.     out    dx,ax
  1072.  
  1073.     mov    dx,03d4h        ; Variations on VGA CRTC synchs
  1074.     mov    ax,13h
  1075.     out    dx,al
  1076.     inc    dx
  1077.     mov    ax,42h
  1078.     out    dx,al
  1079.  
  1080.     mov    dx,03d4h        ; Disable VGA CRTC reg update
  1081.     mov    al,11h
  1082.     out    dx,al
  1083.     inc    dx
  1084.     in    al,dx
  1085.     or    al,80h
  1086.     out    dx,al
  1087.  
  1088.     mov    dx,xga_reg_base        ; Remove CTRC Reset
  1089.     add    dx,0ah
  1090.     mov    al,50h
  1091.     out    dx,al
  1092.     inc    dx
  1093.     in    al,dx
  1094.     or    al,3
  1095.     out    dx,al
  1096.  
  1097.     mov    dx,03c4h        ; 8 bit characters
  1098.     mov    ax,1
  1099.     out    dx,al
  1100.     inc    dx
  1101.     in    al,dx
  1102.     or    al,1
  1103.     out    dx,al
  1104.  
  1105.     mov    dx,03dah        ; Read sets Attr Ctlr flip flop
  1106.     in    al,dx
  1107.  
  1108.     mov    dx,003c0h        ; Sets Attr Ctlr
  1109.     mov    al,13h
  1110.     out    dx,al
  1111.     xor    al,al            ; Reg 13 to 00h
  1112.     out    dx,al
  1113.     mov    al,20h            ; Restore Palette
  1114.     out    dx,al
  1115.  
  1116.     mov    ax,40h            ; tell the BIOS we have 132 columns
  1117.     mov    es,ax
  1118.     mov    byte ptr es:[4ah],132    ; set Bios screen width data area
  1119.     jmp    ok            ; all done!
  1120.  
  1121. nope:
  1122.     mov    ax, offset xga_nullroutine    ; null out the pixel rtns
  1123.     mov    xga_dotwrite,ax
  1124.     mov    xga_dotread,ax
  1125.     mov    xga_linewrite,ax
  1126.     mov    xga_lineread,ax
  1127.     mov    xga_isinmode,0
  1128.     mov    ax,0            ; return failure
  1129.     ret
  1130. ok:
  1131.     mov    ax,mode            ; remember the mode we're in
  1132.     mov    xga_isinmode,ax
  1133.     mov    ax,1            ; return OK
  1134.     ret
  1135. xga_mode    endp
  1136.  
  1137. ; **************** Function xga_getpixel(xdot, ydot) *******************
  1138.  
  1139. ;    Return the color on the screen at the (xdot,ydot) point
  1140.  
  1141. xga_getpixel    proc    uses di si es, xdot:word, ydot:word
  1142.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  1143.     mov    es,ax            ; save it here during this routine
  1144.     mov    cx,xdot         ; load up the registers
  1145.     mov    dx,ydot         ;  for the video routine
  1146.     call    xga_dotread         ; read the dot via the approved method
  1147.     ret                ; we done.
  1148. xga_getpixel    endp
  1149.  
  1150. ; ************** Function xga_putpixel(xdot, ydot, color) *******************
  1151.  
  1152. ;    write the color on the screen at the (xdot,ydot) point
  1153.  
  1154. xga_putpixel    proc    uses di si es, xdot:word, ydot:word, xcolor:word
  1155.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  1156.     mov    es,ax            ; save it here during this routine
  1157.     mov    cx,xdot         ; load up the registers
  1158.     mov    dx,ydot         ;  for the video routine
  1159.     mov    ax,xcolor        ;  ...
  1160.     call    xga_dotwrite        ; write the dot via the approved method
  1161.     ret                ; we done.
  1162. xga_putpixel    endp
  1163.  
  1164. xga_getline    proc uses di si es, row:word, startcol:word, stopcol:word, pixels:word
  1165.     mov    cx,startcol        ; first column
  1166.     mov    dx,row            ; this row
  1167.     mov    ax, stopcol        ; last pixel to read
  1168.     cmp    ax,cx            ; anything to do?
  1169.     jle    xga_sk1            ;  nope
  1170.     mov    di,offset pixels    ; get the color for dot 'x'
  1171.     call    xga_lineread        ; mode-specific lineread routine
  1172. xga_sk1:xor    ax,ax            ; return 0
  1173.     ret
  1174. xga_getline    endp
  1175.  
  1176. xga_putline    proc uses di si es, row:word, startcol:word, stopcol:word, pixels:word
  1177.     mov    cx,startcol        ; first column
  1178.     mov    dx,row            ; this row
  1179.     mov    ax,0a000h        ; EGA, VGA, MCGA, XGA starts here
  1180.     mov    es,ax            ; save it here during this routine
  1181.     mov    ax, stopcol        ; last column
  1182.     cmp    ax,cx            ; anything to do?
  1183.     jle    xga_sk1            ;  nope
  1184.     mov    si,offset pixels    ; put the color for dot 'x'
  1185.     call    xga_linewrite        ; mode-specific linewrite routine
  1186. xga_sk1:xor    ax,ax            ; return 0
  1187.     ret
  1188. xga_putline    endp
  1189.  
  1190.     end
  1191.